﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using Tree.Lifecycle;
using Tree.Injector;
using Tree.Container;
using System.Runtime.Serialization;
using Tree.Configuration;
using System.Configuration;
using System.Globalization;
using Tree.Runner;

namespace Tree.Factory.Impl
{
    public class ObjectFactoryImpl : IObjectFactory
    {
        public T Create<T>(params object[] parameters) 
            where T : class
        {
            Type type = typeof(T);
            object obj = Create(type, parameters);
            return obj as T;
        }

        public object Create(Type type, params object[] parameters)
        {
            if (type.IsInterface)
            {
                type = Core.Resolver.ImplFor(type);
            }

            Type[] parametersType = new Type[0];

            if (parameters != null)
            {
                parametersType = new Type[parameters.Length];
                for (int i = 0; i < parameters.Length; i++)
                {
                    parametersType[i] = parameters[i].GetType();
                }
            }

            object obj = FormatterServices.GetUninitializedObject(type);

            Core.Injector.Inject(obj);
            Core.Injector.Wire(obj);

            if (obj is IConfigurable)
            {
                ConfigurationState state = ObjectConfiguration.GetStateCollection(type);
                ((IConfigurable)obj).Configure(state);
            }

            type.GetConstructor(parametersType).Invoke(obj, parameters);

            if (obj is IInitializable)
            {
                ((IInitializable)obj).Initialize();
            }
            if (obj is IStartable)
            {
                ((IStartable)obj).Start();
            }

            return obj;
        }
    }
}
